package com.lagou.sqlSession;

import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;

import java.lang.reflect.*;
import java.util.List;

public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;

    //脏数据标记
    private boolean dirty;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(MappedStatement mappedStatement, Object... params) throws Exception {
        //将要去完成对simpleExecutor里的query方法的调用
        simpleExecutor simpleExecutor = new simpleExecutor();
        //MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementID);
        List<Object> list = simpleExecutor.query(configuration, mappedStatement, params);

        return (List<E>) list;
    }

    @Override
    public <T> T selectOne(MappedStatement mappedStatement, Object... params) throws Exception {
        List<Object> objects = selectList(mappedStatement, params);
        if (objects.size() == 1) {
            return (T) objects.get(0);
        } else {
            throw new RuntimeException("查询结果为空或者返回结果过多");
        }
    }



    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        Object o = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /*String methodName = method.getName();
                String className = method.getDeclaringClass().getName();*/
                String statementId = getMappedStatementID(method);
                MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
                return  execute(mappedStatement,method,args);
            }
        });
        return (T) o;
    }



    public Object execute(MappedStatement mappedStatement,Method method, Object[] args)throws Exception{
        Object result=null;
        switch (mappedStatement.getCommandType()){
            case SELECT:
                {
                    Type genericReturnType = method.getGenericReturnType();
                    //判断是否进行了泛型类型参数化
                    if (genericReturnType instanceof ParameterizedType) {
                        //准备参数
                        List<Object> objects = selectList(mappedStatement, args);
                        result=objects;
                    }
                    else
                    {
                        result=selectOne(mappedStatement, args);
                    }
                break;}
            case DELETE:{
                result = rowCountResult(method,delete(mappedStatement,args));
                break;}
            case INSERT:{
                result = rowCountResult(method,insert(mappedStatement,args));
                break;
            }
            case UPDATE:{
                result = rowCountResult(method,update(mappedStatement,args));
                break;
            }
            default:
               return null;
        }

        return result;
    }

    private String getMappedStatementID(Method method)
    {
        String methodName = method.getName();
        String className = method.getDeclaringClass().getName();
        return className + "." + methodName;
    }

    private Object rowCountResult(Method method,int rowCount) {
        final Object result;
        if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
            result = rowCount;
        } else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
            result = (long) rowCount;
        } else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
            result = rowCount > 0;
        } else {
            result =null;
        }
        return result;
    }


    @Override
    public Configuration getConfiguration() {
        return null;
    }

    @Override
    public int insert(MappedStatement mappedStatement, Object... parameter)throws Exception {
        simpleExecutor simpleExecutor = new simpleExecutor();
        //MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statement);
        return simpleExecutor.update(configuration,mappedStatement,parameter);
    }

    @Override
    public int update(MappedStatement mappedStatement, Object... parameter) throws Exception {
        simpleExecutor simpleExecutor = new simpleExecutor();
        //MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statement);
        return simpleExecutor.update(configuration,mappedStatement,parameter);
    }


    @Override
    public int delete(MappedStatement mappedStatement, Object... parameter) throws Exception {
        simpleExecutor simpleExecutor = new simpleExecutor();
        //MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statement);
        return simpleExecutor.update(configuration,mappedStatement,parameter);
    }
}
